#include "defines.h"
#include "lista.h"
#include "multiconj_materiales.h"
#include <iostream>
#include <sstream>
#include <string>
#include <cassert>
#include <cstdlib>


using namespace std;


void asegurar(const Multiconj_materiales& l, string s) {
	ostringstream out;
	l.mostrarMulticonj_materiales(out);
	string t = out.str();
	if (s != t) {
		cerr << s << " != " << t << endl;
		assert(false);
	}
}


void asegurar(const Multiconj_materiales& l , const Multiconj_materiales& lp) {
	ostringstream out;
	lp.mostrarMulticonj_materiales(out);
	asegurar(l, out.str());
}


#define RUNTEST(t) { cerr << "Corriendo test " << #t << endl; t (); cerr << "Terminado test " << #t << endl; }



/******************************************************************************************/
/*                               tests sobre las funciones                                */
/******************************************************************************************/

void testVacio(){
	Multiconj_materiales m;
	asegurar(m,"[]");
}


void testAgregar(){
	Multiconj_materiales m;
	m.agregar(3,7);
	asegurar(m,"[<3;7>]");
	m.agregar(3,0);
	asegurar(m,"[<3;7>]");
	m.agregar(4,6);
	asegurar(m,"[<3;7>,<4;6>]");	
	m.agregar(23,42);
	asegurar(m,"[<3;7>,<4;6>,<23;42>]");
	m.agregar(4,10);
	asegurar(m,"[<3;7>,<4;16>,<23;42>]");
	m.agregar(3,100);
	asegurar(m,"[<3;107>,<4;16>,<23;42>]");
	m.agregar(1,0);
	asegurar(m,"[<3;107>,<4;16>,<23;42>]");
}

void testSacar(){
	Multiconj_materiales m;
	m.agregar(3,107);
	m.agregar(4,6);
	m.agregar(23,42);
	m.agregar(7,10);
	asegurar(m,"[<3;107>,<4;6>,<23;42>,<7;10>]");

	m.sacar(7,10);
	asegurar(m,"[<3;107>,<4;6>,<23;42>]");
	m.sacar(3,100);
	asegurar(m,"[<3;7>,<4;6>,<23;42>]");
	m.sacar(4,6);
	asegurar(m,"[<3;7>,<23;42>]");
	m.sacar(7,5);
	asegurar(m,"[<3;7>,<23;42>]");
	m.sacar(23,42);
	asegurar(m,"[<3;7>]");
	m.sacar(7,5);
	asegurar(m,"[<3;7>]");
	m.sacar(3,7);
	asegurar(m,"[]");
}	

void testEsta(){
	Multiconj_materiales m;
	m.agregar(3,107);
	m.agregar(4,6);
	m.agregar(23,42);
	m.agregar(17,10);
	m.agregar(13,12);	
	m.agregar(5,1);
	m.agregar(1,34);
	//El Multiconj me queda  [<3;107>,<4;6>,<23,42>,<17;10>,<13;12>,<5;1>,<1;34>]
	assert(m.esta(3));
	assert(m.esta(4));
	assert(!m.esta(8));
	assert(m.esta(23));	
	assert(!m.esta(34));
	assert(m.esta(13));
	assert(!m.esta(57));
}

void testCardinal(){
	Multiconj_materiales m;
//////********* AGREGO el <3;109> a la lista de materiales ***************/////
	m.agregar(3,109);
	assert(m.cardinal(3)==109);
	m.sacar(3,100);
	assert(m.cardinal(3)==9);
	m.sacar(3,9);
	assert(m.cardinal(3)==0);
//////********* AGREGO el <23;450> a la lista de materiales ***************/////
	m.agregar(23,450);
	assert(m.cardinal(23)==450);
	m.agregar(23,5);
	assert(m.cardinal(23)==455);
	m.sacar(23,455);
	assert(m.cardinal(23)==0);	
//////********* AGREGO el <4;6> a la lista de materiales ***************/////
	m.agregar(4,6);
	assert(m.cardinal(4)==6);
	m.sacar(4,5);
	assert(m.cardinal(4)==1);
	m.sacar(4,1);
	assert(m.cardinal(4)==0);		
}

void testIteraMateriales(){
	Multiconj_materiales m1;
	m1.agregar(4,77);
	m1.agregar(2,54);
	m1.agregar(22,56);
	Multiconj_materiales m2;
	Multiconj_materiales::IterMateriales it1 = m1.crearIterMateriales();
	while(it1.tieneProximo()){
		material mat = it1.avanzar();
		m2.agregar(mat, m1.cardinal(mat));
	}
	assert(m1==m2);
}


int main() {
	RUNTEST(testVacio);
	RUNTEST(testAgregar);
	RUNTEST(testSacar);
	RUNTEST(testEsta);
	RUNTEST(testCardinal);
	RUNTEST(testIteraMateriales);
	return 0;
	
}
